﻿namespace KeRui.Upload
{
    using System;
    using System.Runtime.InteropServices;

    internal class RezFork
    {
        private ResData mData = new ResData();
        private ResHeader mHeader = new ResHeader();
        private ResMap mMap = new ResMap();
        private ResRef mRFL = new ResRef();
        private ResType mRTL = new ResType();
        private SuperStream mStream = null;

        public void GetRezByID(uint inType, ushort inID, out int outData, out int outLen)
        {
            int num = ((int) this.mStream.Length) - 1;
            int num2 = 0;
            int num3 = 0;
            int num4 = 0;
            outData = outLen = 0;
            this.mMap.SetData(this.mStream, this.mHeader.resmap_offset);
            if ((this.mMap.offset + this.mHeader.resmap_length) <= num)
            {
                this.mRTL.SetData(this.mStream, (this.mMap.offset + this.mMap.resourcetypelist_offset) + 2);
                if (this.mRTL.offset <= num)
                {
                    num2 = this.mMap.numtypes_zbased + 1;
                    if ((this.mRTL.offset + (this.mRTL.size * num2)) <= num)
                    {
                        this.mRFL.offset = 0;
                        for (num4 = 0; num4 < num2; num4++)
                        {
                            if (this.mRTL.restype == inType)
                            {
                                this.mRFL.SetData(this.mStream, (this.mRTL.offset + this.mRTL.referencelist_offset) - 4);
                                num3 = this.mRTL.numres_zbased + 1;
                                break;
                            }
                            this.mRTL.SetData(this.mStream, this.mRTL.offset + this.mRTL.size);
                        }
                        if ((this.mRFL.offset != 0) && ((this.mRFL.offset + (this.mRFL.size * num3)) <= num))
                        {
                            this.mData.offset = 0;
                            for (num4 = 0; num4 < num3; num4++)
                            {
                                if (this.mRFL.resid == inID)
                                {
                                    this.mData.SetData(this.mStream, this.mHeader.resdata_offset + this.mRFL.attr_data_offset);
                                    break;
                                }
                                this.mRFL.SetData(this.mStream, this.mRFL.offset + this.mRFL.size);
                            }
                            if ((this.mData.offset != 0) && ((this.mData.res_length >= 0) && (((this.mData.offset + this.mData.size) + this.mData.res_length) <= num)))
                            {
                                outData = this.mData.offset + this.mData.size;
                                outLen = this.mData.res_length;
                            }
                        }
                    }
                }
            }
        }

        public bool IsOK()
        {
            if (this.mStream.Length < this.mHeader.size)
            {
                return false;
            }
            if (this.mHeader.resdata_offset < this.mHeader.size)
            {
                return false;
            }
            if (this.mHeader.resmap_offset < this.mHeader.size)
            {
                return false;
            }
            if (this.mHeader.resdata_length < 0)
            {
                return false;
            }
            if (this.mHeader.resmap_length < 0)
            {
                return false;
            }
            if (this.mHeader.resdata_offset > this.mHeader.resmap_offset)
            {
                if ((this.mHeader.resmap_offset + this.mHeader.resmap_length) > this.mHeader.resdata_offset)
                {
                    return false;
                }
                if ((this.mHeader.resdata_offset + this.mHeader.resdata_length) != this.mStream.Length)
                {
                    return false;
                }
            }
            else
            {
                if ((this.mHeader.resdata_offset + this.mHeader.resdata_length) > this.mHeader.resmap_offset)
                {
                    return false;
                }
                if ((this.mHeader.resmap_offset + this.mHeader.resmap_length) != this.mStream.Length)
                {
                    return false;
                }
            }
            return true;
        }

        public void SetData(SuperStream inStream)
        {
            this.mStream = inStream;
            this.mHeader.SetData(inStream, 0);
        }

        private class ResData
        {
            public int offset;
            public int res_length;
            public int size;

            public void SetData(SuperStream inStream, int inOffset)
            {
                this.size = 8;
                this.offset = inOffset;
                inStream.Position = this.offset;
                this.res_length = inStream.GetMacLONG();
            }
        }

        private class ResHeader
        {
            public int offset;
            public int resdata_length;
            public int resdata_offset;
            public int resmap_length;
            public int resmap_offset;
            public int size;

            public void SetData(SuperStream inStream, int inOffset)
            {
                this.size = 0x10;
                this.offset = inOffset;
                inStream.Position = this.offset;
                this.resdata_offset = inStream.GetMacLONG();
                inStream.Position = this.offset + 4;
                this.resmap_offset = inStream.GetMacLONG();
                inStream.Position = this.offset + 8;
                this.resdata_length = inStream.GetMacLONG();
                inStream.Position = this.offset + 12;
                this.resmap_length = inStream.GetMacLONG();
            }
        }

        private class ResMap
        {
            public ushort numtypes_zbased;
            public int offset;
            public ushort resourcetypelist_offset;

            public void SetData(SuperStream inStream, int inOffset)
            {
                this.offset = inOffset;
                inStream.Position = this.offset + 0x18;
                this.resourcetypelist_offset = inStream.GetMacWORD();
                inStream.Position = this.offset + 0x1c;
                this.numtypes_zbased = inStream.GetMacWORD();
            }
        }

        private class ResRef
        {
            public int attr_data_offset;
            public int offset;
            public ushort resid;
            public int size;

            public void SetData(SuperStream inStream, int inOffset)
            {
                this.size = 12;
                this.offset = inOffset;
                inStream.Position = this.offset;
                this.resid = inStream.GetMacWORD();
                inStream.Position = this.offset + 4;
                this.attr_data_offset = inStream.GetMacLONG();
                this.attr_data_offset = (this.attr_data_offset & 0xffffff) << 8;
            }
        }

        private class ResType
        {
            public ushort numres_zbased;
            public int offset;
            public ushort referencelist_offset;
            public uint restype;
            public int size;

            public void SetData(SuperStream inStream, int inOffset)
            {
                this.size = 8;
                this.offset = inOffset;
                inStream.Position = this.offset;
                this.restype = inStream.GetMacDWORD();
                inStream.Position = this.offset + 4;
                this.numres_zbased = inStream.GetMacWORD();
                inStream.Position = this.offset + 6;
                this.referencelist_offset = inStream.GetMacWORD();
            }
        }
    }
}

